package handler

import (
	"strconv"
	"time"

	"project-info/src/handle/common"
	"project-info/src/handle/response"
	"project-info/src/model"

	"project-info/src/lib")

// ScopeRequest 作用域请求结构
type ScopeRequest struct {
	ScopeName         string              `json:"scopeName" binding:"required"`
	DisplayName       string              `json:"displayName" binding:"required"`
	Description       string              `json:"description"`
	IsDefault         bool                `json:"isDefault"`
	Claims            []string            `json:"claims"`
	RoleMapping       map[string][]string `json:"roleMapping"`
	PermissionMapping map[string]string   `json:"permissionMapping"`
	Status            int                 `json:"status"`
}

// ScopeResponse 作用域响应结构
type ScopeResponse struct {
	ID                uint                `json:"id"`
	ScopeName         string              `json:"scopeName"`
	DisplayName       string              `json:"displayName"`
	Description       string              `json:"description"`
	IsDefault         bool                `json:"isDefault"`
	Claims            []string            `json:"claims"`
	RoleMapping       map[string][]string `json:"roleMapping,omitempty"`
	PermissionMapping map[string]string   `json:"permissionMapping,omitempty"`
	Status            int                 `json:"status"`
	CreateTime        time.Time           `json:"createTime"`
	UpdateTime        time.Time           `json:"updateTime,omitempty"`
	Creator           string              `json:"creator,omitempty"`
	Modifier          string              `json:"modifier,omitempty"`
}

// ScopeListResponse 作用域列表响应结构
type ScopeListResponse struct {
	Total int             `json:"total"`
	Page  int             `json:"page"`
	Size  int             `json:"size"`
	Items []ScopeResponse `json:"items"`
}

// CreateScope 创建新的作用域
// POST /oidc/admin/scopes
func CreateScope(c *lib.GinContext) error {
	var req ScopeRequest
	if err := c.Bind(&req); err != nil {
		return response.JsonFail(c, "参数错误")
	}

	// 验证作用域名称是否已存在
	db := model.DB()
	var existingScope model.OIDCScope
	if err := db.Where("scope_name = ? AND deleted = 0", req.ScopeName).First(&existingScope).Error; err == nil {
		return response.JsonFail(c, "作用域名称已存在")
	}

	// 设置默认值
	if req.Status == 0 {
		req.Status = 1 // 默认启用
	}
	if len(req.Claims) == 0 {
		req.Claims = []string{} // 默认空声明
	}

	// 创建作用域
	oidcScope := model.OIDCScope{
		ScopeName:   req.ScopeName,
		DisplayName: req.DisplayName,
		Description: req.Description,
		IsDefault:   req.IsDefault,
		Claims:      model.JSONArray(req.Claims),
		Status:      req.Status,
	}

	if err := db.Create(&oidcScope).Error; err != nil {
		return response.JsonFail(c, "创建作用域失败")
	}

	// 返回创建的作用域信息
	scopeResp := ScopeResponse{
		ID:                uint(oidcScope.Id),
		ScopeName:         oidcScope.ScopeName,
		DisplayName:       oidcScope.DisplayName,
		Description:       oidcScope.Description,
		IsDefault:         oidcScope.IsDefault,
		Claims:            []string(oidcScope.Claims),
		RoleMapping:       req.RoleMapping,
		PermissionMapping: req.PermissionMapping,
		Status:            oidcScope.Status,
		CreateTime:        *oidcScope.CreateTime,
		Creator:           oidcScope.Creator,
	}

	return response.JsonOk(c, scopeResp, "作用域创建成功")
}

// ListScopes 获取作用域列表
// GET /oidc/admin/scopes
func ListScopes(c *lib.GinContext) error {
	// 获取分页参数
	pagination := parsePaginationParams(c)

	// 获取其他查询参数
	scopeName := c.QueryParam("scopeName")
	statusStr := c.QueryParam("status")

	db := model.DB()
	query := db.Where("deleted = 0")

	// 应用过滤条件
	if scopeName != "" {
		query = query.Where("scope_name LIKE ?", "%"+scopeName+"%")
	}
	if statusStr != "" {
		if status, err := strconv.Atoi(statusStr); err == nil {
			query = query.Where("status = ?", status)
		}
	}

	// 计算总数
	var total int64
	query.Model(&model.OIDCScope{}).Count(&total)

	// 分页查询
	var oidcScopes []model.OIDCScope
	query.Order("create_time DESC").Offset(pagination.Offset).Limit(pagination.Size).Find(&oidcScopes)

	scopes := make([]ScopeResponse, 0)
	for _, oidcScope := range oidcScopes {
		scopeResp := ScopeResponse{
			ID:          uint(oidcScope.Id),
			ScopeName:   oidcScope.ScopeName,
			DisplayName: oidcScope.DisplayName,
			Description: oidcScope.Description,
			IsDefault:   oidcScope.IsDefault,
			Claims:      []string(oidcScope.Claims),
			Status:      oidcScope.Status,
			CreateTime:  *oidcScope.CreateTime,
			Creator:     oidcScope.Creator,
		}

		if oidcScope.UpdateTime != nil {
			scopeResp.UpdateTime = *oidcScope.UpdateTime
			scopeResp.Modifier = oidcScope.Modifier
		}

		scopes = append(scopes, scopeResp)
	}

	r := ScopeListResponse{
		Total: int(total),
		Page:  pagination.Page,
		Size:  pagination.Size,
		Items: scopes,
	}

	return response.JsonOk(c, r, "获取成功")
}

// GetScope 获取单个作用域信息
// GET /oidc/admin/scopes/{id}
func GetScope(c *lib.GinContext) error {
	scopeID := c.QueryParam("id")
	if scopeID == "" {
		return response.JsonFail(c, "缺少作用域ID参数")
	}

	db := model.DB()
	var oidcScope model.OIDCScope
	if err := db.Where("id = ? AND deleted = 0", scopeID).First(&oidcScope).Error; err != nil {
		return response.JsonFail(c, "作用域不存在")
	}

	scopeResp := ScopeResponse{
		ID:          uint(oidcScope.Id),
		ScopeName:   oidcScope.ScopeName,
		DisplayName: oidcScope.DisplayName,
		Description: oidcScope.Description,
		IsDefault:   oidcScope.IsDefault,
		Claims:      []string(oidcScope.Claims),
		Status:      oidcScope.Status,
		CreateTime:  *oidcScope.CreateTime,
		Creator:     oidcScope.Creator,
	}

	if oidcScope.UpdateTime != nil {
		scopeResp.UpdateTime = *oidcScope.UpdateTime
		scopeResp.Modifier = oidcScope.Modifier
	}

	return response.JsonOk(c, scopeResp, "获取成功")
}

// UpdateScope 更新作用域信息
// PUT /oidc/admin/scopes/{id}
func UpdateScope(c *lib.GinContext) error {
	scopeID := c.QueryParam("id")
	if scopeID == "" {
		return response.JsonFail(c, "缺少作用域ID参数")
	}

	// 查询作用域是否存在
	db := model.DB()
	var oidcScope model.OIDCScope
	if err := db.Where("id = ? AND deleted = 0", scopeID).First(&oidcScope).Error; err != nil {
		return response.JsonFail(c, "作用域不存在")
	}

	var req ScopeRequest
	if err := c.Bind(&req); err != nil {
		return response.JsonFail(c, "参数错误")
	}

	// 检查作用域名称是否与其他作用域冲突
	if req.ScopeName != oidcScope.ScopeName {
		var existingScope model.OIDCScope
		if err := db.Where("scope_name = ? AND id != ? AND deleted = 0", req.ScopeName, scopeID).First(&existingScope).Error; err == nil {
			return response.JsonFail(c, "作用域名称已存在")
		}
	}

	// 更新作用域信息
	oidcScope.ScopeName = req.ScopeName
	oidcScope.DisplayName = req.DisplayName
	oidcScope.Description = req.Description
	oidcScope.IsDefault = req.IsDefault
	oidcScope.Claims = model.JSONArray(req.Claims)
	oidcScope.Status = req.Status

	if err := db.Save(&oidcScope).Error; err != nil {
		return response.JsonFail(c, "更新作用域失败")
	}

	// 返回更新后的作用域信息
	scopeResp := ScopeResponse{
		ID:                uint(oidcScope.Id),
		ScopeName:         oidcScope.ScopeName,
		DisplayName:       oidcScope.DisplayName,
		Description:       oidcScope.Description,
		IsDefault:         oidcScope.IsDefault,
		Claims:            []string(oidcScope.Claims),
		RoleMapping:       req.RoleMapping,
		PermissionMapping: req.PermissionMapping,
		Status:            oidcScope.Status,
		CreateTime:        *oidcScope.CreateTime,
		UpdateTime:        *oidcScope.UpdateTime,
		Creator:           oidcScope.Creator,
		Modifier:          oidcScope.Modifier,
	}

	return response.JsonOk(c, scopeResp, "更新成功")
}

// DeleteScope 删除作用域
// DELETE /oidc/admin/scopes/{id}
func DeleteScope(c *lib.GinContext) error {
	scopeID := c.QueryParam("id")
	if scopeID == "" {
		return response.JsonFail(c, "缺少作用域ID参数")
	}

	// 查询作用域是否存在
	db := model.DB()
	var oidcScope model.OIDCScope
	if err := db.Where("id = ? AND deleted = 0", scopeID).First(&oidcScope).Error; err != nil {
		return response.JsonFail(c, "作用域不存在")
	}

	// 检查是否为默认作用域，默认作用域不能删除
	if oidcScope.IsDefault {
		return response.JsonFail(c, "默认作用域不能删除")
	}

	// 检查是否有客户端正在使用此作用域
	var clientCount int64
	db.Model(&model.OIDCClient{}).Where("deleted = 0 AND JSON_CONTAINS(scopes, ?)", `"`+oidcScope.ScopeName+`"`).Count(&clientCount)
	if clientCount > 0 {
		return response.JsonFail(c, "该作用域正在被客户端使用，无法删除")
	}

	// 软删除作用域
	oidcScope.Deleted = 1
	now := time.Now()
	oidcScope.UpdateTime = &now
	if err := db.Save(&oidcScope).Error; err != nil {
		return response.JsonFail(c, "删除作用域失败")
	}

	return response.JsonOk(c, nil, "删除成功")
}

// GetScopeOptions 获取作用域选项
// GET /oidc/admin/scopes/options
func GetScopeOptions(c *lib.GinContext) error {
	db := model.DB()
	var oidcScopes []model.OIDCScope
	if err := db.Where("deleted = 0").Find(&oidcScopes).Error; err != nil {
		return response.JsonFail(c, "获取作用域列表失败")
	}

	scopeOptions := []common.OptionRes{}
	for _, scope := range oidcScopes {
		scopeOptions = append(scopeOptions, common.OptionRes{
			Label: scope.DisplayName,
			Value: scope.ScopeName,
		})
	}

	return response.JsonOk(c, scopeOptions, "获取成功")
}
